<template>
  <div class="course-directory">
    <!-- 新增章节按钮，右上角 -->
    <div class="flex mb-4">
      <el-button type="primary" @click="addChapter">
        {{ $t('course.addChapter') }}
      </el-button>
    </div>
    <el-tree :data="treeData" node-key="id" :props="defaultProps" :expand-on-click-node="false" class="w-full"
      default-expand-all>
      <template #default="{ node, data }">
        <div class="flex justify-between w-full">
          <div class="flex items-center">
            <template v-if="isFile(data)">
              <el-tag v-if="data.contentType === CONTENT_TYPE.VIDEO" type="primary" size="small" effect="light"
                class="mr-1">{{ $t('course.video') }}</el-tag>
              <el-tag v-else-if="data.contentType === CONTENT_TYPE.ARTICLE" type="success" size="small" effect="light"
                class="mr-1">{{ $t('course.article') }}</el-tag>
              <el-tag v-else-if="data.contentType === CONTENT_TYPE.DOCUMENT" color="#13C2C233" size="small"
                effect="light" class="mr-1 text-[#149595]">{{ $t('course.document') }}</el-tag>
            </template>
            <span>{{ data.name }}</span>
          </div>
          <div class="flex gap-1">
            <!-- 第一层：章节 -->
            <template v-if="isChapter(data)">
              <el-tooltip effect="dark" :content="$t('course.addSubSectionTxt')" :show-after="500" placement="top">
                <el-button :icon="SvgAddChildIcon" link @click.stop="addSubSection(data)"></el-button>
              </el-tooltip>
              <el-tooltip effect="dark" :content="$t('course.addContent')" :show-after="500" placement="top">
                <el-button :icon="FilePlus2" link @click.stop="addFile(data)"></el-button>
              </el-tooltip>
              <el-tooltip effect="dark" :content="$t('common.editTxt')" :show-after="500" placement="top">
                <el-button :icon="Pencil" link @click.stop="editNode(data, node)"></el-button>
              </el-tooltip>
              <el-tooltip effect="dark" :content="$t('common.deleteTxt')" :show-after="500" placement="top">
                <el-button :icon="Trash2" link @click.stop="deleteNode(data, node)"></el-button>
              </el-tooltip>
            </template>
            <!-- 第二层：子章节 -->
            <template v-else-if="isSubSection(data)">
              <el-tooltip effect="dark" :content="$t('course.addContent')" :show-after="500" placement="top">
                <el-button :icon="FilePlus2" link @click.stop="addFile(data)"></el-button>
              </el-tooltip>
              <el-tooltip effect="dark" :content="$t('common.editTxt')" :show-after="500" placement="top">
                <el-button :icon="Pencil" link @click.stop="editNode(data, node)"></el-button>
              </el-tooltip>
              <el-tooltip effect="dark" :content="$t('common.deleteTxt')" :show-after="500" placement="top">
                <el-button :icon="Trash2" link @click.stop="deleteNode(data, node)"></el-button>
              </el-tooltip>
            </template>
            <!-- 第三层：文件 -->
            <template v-else>
              <el-tooltip effect="dark" :content="$t('common.editTxt')" :show-after="500" placement="top">
                <el-button :icon="Pencil" link @click.stop="editNode(data, node)"></el-button>
              </el-tooltip>
              <el-tooltip effect="dark" :content="$t('common.deleteTxt')" :show-after="500" placement="top">
                <el-button :icon="Trash2" link @click.stop="deleteNode(data, node)"></el-button>
              </el-tooltip>
            </template>
          </div>
        </div>
      </template>
    </el-tree>
    <!-- 新增和编辑章节弹窗 -->
    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="500px" :close-on-click-modal="false">
      <el-form ref="formRef" :model="formData" :rules="rules" label-width="100px" @submit.prevent>
        <el-form-item :label="dialogLabel" prop="name">
          <el-input v-model.trim="formData.name" :placeholder="$t('common.inputPhTxt', [dialogLabel])" maxlength="50"
            @keydown.enter.prevent />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">{{ $t('common.cancelTxt') }}</el-button>
        <el-button type="primary" @click="handleDialogConfirm">{{ $t('common.submitTxt') }}</el-button>
      </template>
    </el-dialog>
    <!-- 文件的上传弹窗 -->
    <ContentFileDialog v-model:visible="contentFileDialogVisible" :mode="contentFileDialogMode"
      :data="contentFileDialogData" @submit="handleContentFileSubmit" @cancel="contentFileDialogVisible = false" />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, shallowRef } from 'vue'
import { Pencil, FilePlus2, Trash2, SvgAddChildIcon } from '@vben/icons'
import { $t } from '#/locales/index.js'
import ContentFileDialog from './content-file-dialog.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { NODE_TYPE, DIALOG_MODE, type NodeType, type DialogMode, type TreeNode, CONTENT_TYPE } from './types'
import { obsDelete } from "#/utils/obs"
import { SvgFailIcon, SvgTipIcon, SvgSuccessIcon } from '@vben/icons'

const treeData = ref<TreeNode[]>([])
const defaultProps = {
  children: 'content',
  label: 'name'
}

const props = defineProps<{
  data: any
}>()
const deleteChapterIds = shallowRef<string[]>([])
// 弹窗相关
const dialogVisible = ref(false)
const dialogType = ref<NodeType>(NODE_TYPE.CHAPTER)
const dialogMode = ref<DialogMode>(DIALOG_MODE.ADD)
const formRef = ref()
const formData = reactive({ name: '' })
const currentNode = ref<any>(null)
const contentFileDialogVisible = ref(false)
const contentFileDialogMode = ref<DialogMode>(DIALOG_MODE.EDIT)
const contentFileDialogData = ref<any>({})
const isDialogChapter = computed(() => dialogType.value === NODE_TYPE.CHAPTER)
const dialogLabel = computed(() => dialogType.value === NODE_TYPE.CHAPTER ? $t('courseMgr.chapterName') : $t('courseMgr.subSectionName'))
const rules = {
  name: [
    { required: true, message: `${$t('common.inputPhTxt', [dialogLabel.value])}`, trigger: 'blur' },
    {
      validator: (rule: any, value: any, callback: any) => {
        const list = isDialogChapter.value ? treeData.value : currentNode.value?.content || []
        const isDuplicate = list.some((item: any) => item.name === value)
        if (isDuplicate) {
          callback(new Error(`${dialogLabel.value}${$t('courseMgr.duplicateNotAllowed')}`))
        } else {
          callback()
        }
      }, trigger: 'blur'
    }
  ]
}

const dialogTitle = computed(() => {
  if (dialogType.value === NODE_TYPE.CHAPTER) {
    return dialogMode.value === DIALOG_MODE.ADD ? $t('course.addChapter') : $t('course.editChapter')
  } else {
    return dialogMode.value === DIALOG_MODE.ADD ? $t('course.addSubSection') : $t('course.editSubSection')
  }
})

watch(dialogVisible, (newVal) => {
  if (!newVal) {
    formRef.value?.resetFields()
    currentNode.value = null
  }
})

function showDialog(type: NodeType, mode: DialogMode, node?: any) {
  dialogType.value = type
  dialogMode.value = mode
  dialogVisible.value = true
  if (mode === DIALOG_MODE.EDIT && node) {
    formData.name = node.name
    currentNode.value = node
  } else {
    formData.name = ''
    currentNode.value = node || null
  }
}
const isChapter = (node: any) => node.type === NODE_TYPE.CHAPTER
const isSubSection = (node: any) => node.type === NODE_TYPE.SUB
const isFile = (node: any) => node.type === NODE_TYPE.FILE

// 排序函数：章节 → 子章节 → 文件
const sortNodesByType = (nodes: any[]) => {
  const sortOrder: Record<string, number> = {
    [NODE_TYPE.CHAPTER]: 1,
    [NODE_TYPE.SUB]: 2,
    [NODE_TYPE.FILE]: 3
  }
  return nodes.slice().sort((a: any, b: any) => {
    return (sortOrder[a.type as string] || 999) - (sortOrder[b.type as string] || 999)
  })
}
const addChapter = () => showDialog(NODE_TYPE.CHAPTER, DIALOG_MODE.ADD)
const addSubSection = (node: any) => showDialog(NODE_TYPE.SUB, DIALOG_MODE.ADD, node)

const addFile = (node: any) => {
  contentFileDialogMode.value = DIALOG_MODE.ADD
  contentFileDialogData.value = { parentNode: node }
  contentFileDialogVisible.value = true
}

function editNode(node: any, nodeTree?: any) {
  if (node.type === NODE_TYPE.CHAPTER) showDialog(NODE_TYPE.CHAPTER, DIALOG_MODE.EDIT, node)
  else if (node.type === NODE_TYPE.SUB) showDialog(NODE_TYPE.SUB, DIALOG_MODE.EDIT, node)
  else if (node.type === NODE_TYPE.FILE) {
    contentFileDialogMode.value = DIALOG_MODE.EDIT
    contentFileDialogData.value = { ...node, treeNodeId: node.$treeNodeId, parentNode: nodeTree.parent.data }
    contentFileDialogVisible.value = true
  }
}
// 批量删除OBS文件的方法
const batchDeleteObsFiles = async (filePaths: string[]): Promise<boolean> => {
  if (!filePaths || filePaths.length === 0) {
    return true
  }
  try {
    // 创建所有删除操作的Promise
    const deletePromises = filePaths.map((path) => {
      return new Promise<void>((resolve, reject) => {
        obsDelete({
          Key: path
        }, (err: any, result: any) => {
          if (err) {
            reject(err)
          } else {
            resolve()
          }
        })
      })
    })
    // 等待所有删除操作完成
    await Promise.all(deletePromises)
    ElMessage.success($t('courseMgr.fileDeleteSuccess'))
    return true
  } catch (error) {
    console.error($t('courseMgr.batchDeleteFail'), error)
    ElMessage.error($t('courseMgr.fileDeleteFail'))
    return false
  }
}

const deleteNodeFromTree = (parentData: any, treeNodeId?: any) => {
  if (parentData && treeNodeId) {
    const index = parentData.findIndex((item: any) => item.$treeNodeId === treeNodeId)
    if (index !== -1) {
      parentData.splice(index, 1)
    }
  }
}

const deleteNode = async (node: any, nodeTree?: any) => {
  const treeNodeId = node.$treeNodeId
  const parentData = isChapter(node) ? nodeTree.parent.data : nodeTree.parent.data.content
  console.log('deleteNode', node, nodeTree, parentData, treeNodeId)
  try {
    // 显示确认对话框
    await ElMessageBox.confirm(
      $t('courseMgr.deleteConfirmWithName', { name: node.name }),
      '',
      {
        icon: SvgFailIcon,
        confirmButtonText: $t('common.submitTxt'),
        cancelButtonText: $t('common.cancelTxt'),
        type: 'warning',
      }
    )
    // 如果是文件类型且有path，需要从OBS删除文件
    if (isFile(node)) {
      if (node.path) {
        // 删除OBS文件成功后再删除节点
        const deleteSuccess = await batchDeleteObsFiles([node.path])
        if (!deleteSuccess) {
          return // 如果删除失败，不继续执行删除节点操作
        }
      }
    } else {
      if (isChapter(node) && node.id) {
        deleteChapterIds.value.push(node.id)
      }
      // 递归遍历节点下的所有数据，删除文件类型的OBS文件
      const deleteFilesFromNode = (node: any) => {
        if (isFile(node) && node.path) {
          batchDeleteObsFiles([node.path])
        }
        // 递归处理子节点
        if (node.content && Array.isArray(node.content)) {
          node.content.forEach((childNode: any) => {
            deleteFilesFromNode(childNode)
          })
        }
      }
      // 执行删除操作
      deleteFilesFromNode(node)
    }
    deleteNodeFromTree(parentData, treeNodeId)
  } catch (error) {
    // 用户取消删除
    console.log($t('common.deleteCancelledTxt'))
  }
}

// 表单校验方法
const validate = async () => {
  // 课程目录暂时没有校验
  return true
}

// 重置表单
const resetForm = () => {
  // 课程目录暂时没有需要重置的内容
}

async function handleDialogConfirm() {
  try {
    await formRef.value.validate()
    console.log('formData', formData)
    if (dialogMode.value === DIALOG_MODE.ADD) {
      if (dialogType.value === NODE_TYPE.CHAPTER) {
        // 新增章节
        treeData.value.push({
          // id: Date.now(),
          name: formData.name,
          type: NODE_TYPE.CHAPTER,
          content: []
        })

        // 对 treeData.value 进行排序
        treeData.value = sortNodesByType(treeData.value)
        console.log('treeData', treeData.value)
      } else {
        // 新增子章节
        const node = currentNode.value
        if (node) {
          if (!node.content || !Array.isArray(node.content)) {
            node.content = []
          }
          node.content.push({
            // id: Date.now(),
            name: formData.name,
            type: NODE_TYPE.SUB,
            content: []
          })
          // 修正 node.content 的数据结构，确保每个子节点有唯一 id，并按 type 排序
          node.content = sortNodesByType(
            node.content.map((item: any, idx: number) => ({
              ...item,
              // id: item.id ?? Date.now() + idx // 如果没有 id，则生成一个唯一 id
            }))
          )
        }
      }
    } else {
      // 编辑章节
      const node = currentNode.value
      if (node) {
        node.name = formData.name
      }
    }
    dialogVisible.value = false
  } catch (error) {
    // ElMessage.error('请检查表单信息')
  }
}

function handleContentFileSubmit(data: any) {
  console.log('Content file submitted:', contentFileDialogData.value, data)
  const node = contentFileDialogData.value?.parentNode
  if (node && !contentFileDialogData.value?.treeNodeId) {
    // 确保 content 数组存在
    if (!node.content) {
      node.content = []
    }
    // 添加 id 属性
    const fileData = {
      ...data,
      // id: Date.now(),
    }
    node.content.push(fileData)
  } else {
    const node = contentFileDialogData.value?.parentNode
    if (node) {
      node.content.forEach((item: any, index: number) => {
        if (item.$treeNodeId === contentFileDialogData.value?.treeNodeId) {
          node.content[index] = data
        }
      })
    }
  }
  // 这里处理文件内容编辑后的数据
  contentFileDialogVisible.value = false
}

defineExpose({
  validate,
  resetForm,
  getTreeData: () => treeData.value,
  setTreeData: (data: any) => {
    // 确保传入的数据是数组
    if (!Array.isArray(data)) {
      treeData.value = []
      return
    }
    // 确保每个节点的content属性是数组
    treeData.value = data.map((item: any) => ({
      ...item,
      content: Array.isArray(item.content) ? item.content : []
    }))
  },
  setDeleteChapterIds: (ids: any) => deleteChapterIds.value = Array.isArray(ids) ? ids : [],
  getDeleteChapterIds: () => deleteChapterIds.value
})
</script>

<style scoped>
.course-directory {
  padding: 0px 0;
}

/* 只对第一层树节点设置背景色 */
:deep(.el-tree > .el-tree-node > .el-tree-node__content) {
  background: #f2f7fd;
}

/* 保持其他层级的默认样式 */
:deep(.el-tree-node__content) {
  border-bottom: 1px solid #e3e3e3;
  height: 40px;
  padding: 0 48px 0 24px !important;
}

/* 修改树节点展开/折叠三角按钮样式 */
:deep(.el-tree-node__expand-icon) {
  width: 20px !important;
  height: 20px !important;
  color: #595959 !important;
  font-size: 20px !important;
}

/* 确保三角图标的颜色 */
:deep(.el-tree-node__expand-icon svg) {
  width: 20px !important;
  height: 20px !important;
  fill: #595959 !important;
}

</style>
